import 'package:dio/dio.dart';
import 'package:logger/logger.dart';
import 'package:lunar/calendar/Fu.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../config/api_config.dart';
import '../models/git_commit.dart';
import '../models/git_repo.dart';
import '../models/git_tree_item.dart';
import '../models/git_blob.dart';
import '../models/git_branch.dart';

class ApiService {
  static final ApiService _instance = ApiService._internal();
  late final Dio _dio;
  static const String _tokenKey = 'gitee_access_token';
  static const String _owner = 'bndg';

  factory ApiService() => _instance;
  final logger = Logger();

  ApiService._internal() {
    _dio = Dio(BaseOptions(
      baseUrl: ApiConfig.baseUrl,
      connectTimeout: const Duration(milliseconds: ApiConfig.connectTimeout),
      receiveTimeout: const Duration(milliseconds: ApiConfig.receiveTimeout),
    ));
    // 添加拦截器打印日志
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) async {
        // 从SharedPreferences获取token
        // 登录接口不需要token
        return handler.next(options);
      },
      onResponse: (response, handler) async {
        logger.i('响应体: ${response.headers}');
        return handler.next(response);
      },
      onError: (DioException e, handler) async {
        logger.e('错误: ${e.response?.statusCode} ${e.response?.data}');
        if (e.response != null && e.response!.statusCode == 401) {
          await clearAccessToken();
          return handler.reject(DioException(
            requestOptions: e.requestOptions,
            type: DioExceptionType.badResponse,
            response: e.response,
            error: '登录已过期，请重新登录',
          ));
        }
        return handler.next(e);
      },
    ));
    _dio.interceptors.add(
      PrettyDioLogger(
        requestHeader: true,
        requestBody: true,
        filter: (options, args) {
          //  return !options.uri.path.contains('posts');
          return !args.isResponse || !args.hasUint8ListData;
        },
      ),
    );
  }

  // 获取保存的token
  Future<String?> getAccessToken() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString(_tokenKey);
  }

  // 保存token
  Future<void> saveAccessToken(String token) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(_tokenKey, token);
  }

  // 清除token
  Future<void> clearAccessToken() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove(_tokenKey);
  }

  // 获取用户仓库列表
  Future<List<GitRepo>> getUserRepos({
    int page = 1,
    int perPage = ApiConfig.defaultPageSize,
    String sort = ApiConfig.defaultSort,
  }) async {
    try {
      final token = await getAccessToken();
      if (token == null) {
        throw Exception('Access token not found');
      }

      final response = await _dio.get(
        ApiConfig.userRepos,
        queryParameters: {
          'sort': sort,
          'page': page,
          'per_page': perPage,
          'access_token': token,
        },
      );

      if (response.statusCode == 200) {
        final List<dynamic> data = response.data;
        return data.map((json) => GitRepo.fromJson(json)).toList();
      } else {
        logger.e('Failed : ${response.statusMessage}');
        throw Exception('Failed to load repos: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Failed to load repos: $e');
    }
  }

  // 设置认证token
  void setAuthToken(String token) {
    _dio.options.headers['Authorization'] = 'Bearer $token';
  }

  // 清除认证token
  void clearAuthToken() {
    _dio.options.headers.remove('Authorization');
  }

  // 获取仓库目录 sha可以是分支名(如master)、Commit或者目录Tree的SHA值
  Future<List<GitTreeItem>> getRepoTree({
    String owner = _owner,
    required String repo,
    required String sha,
  }) async {
    try {
      final response = await _dio.get(
        '/api/v5/repos/$owner/$repo/git/trees/$sha',
        queryParameters: {'access_token': await getAccessToken()},
      );

      if (response.statusCode == 200) {
        final Map<String, dynamic> data = response.data;
        final List<dynamic> tree = data['tree'];
        return tree.map((json) => GitTreeItem.fromJson(json)).toList();
      } else {
        throw Exception('Failed to load repo tree: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Failed to load repo tree: $e');
    }
  }

  // 获取文件内容
  Future<GitBlob> getFileContent({
    String owner = _owner,
    required String repo,
    required String sha,
  }) async {
    try {
      final response = await _dio.get(
        '/api/v5/repos/$owner/$repo/git/blobs/$sha',
        queryParameters: {'access_token': await getAccessToken()},
      );

      if (response.statusCode == 200) {
        return GitBlob.fromJson(response.data);
      } else {
        throw Exception('Failed to load file content: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Failed to load file content: $e');
    }
  }

  Future<List<GitCommit>> getGitLog(
      String owner, String repo, String branch, int page) async {
    final response = await _dio.get(
      '/api/v5/repos/$owner/$repo/commits',
      queryParameters: {
        'sha': branch,
        'page': page,
        'per_page': ApiConfig.defaultPageSize,
        'access_token': await getAccessToken()
      },
    );
    if (response.statusCode == 200) {
      return (response.data as List).map((e) => GitCommit.fromJson(e)).toList();
    } else {
      throw Exception('Failed to load file content');
    }
  }

  // 获取仓库分支列表
  Future<List<GitBranch>> getRepoBranches({
    required String owner,
    required String repo,
  }) async {
    try {
      final response = await _dio.get(
        '/api/v5/repos/$owner/$repo/branches',
        queryParameters: {'access_token': await getAccessToken()},
      );

      if (response.statusCode == 200) {
        final List<dynamic> data = response.data;
        return data.map((json) => GitBranch.fromJson(json)).toList();
      } else {
        throw Exception('Failed to load branches: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Failed to load branches: $e');
    }
  }

  uploadFile(
      {String owner = _owner,
      required String repo,
      required String path,
      required String content,
      required String message}) async {
    final response = await _dio.post(
      '/api/v5/repos/$owner/$repo/contents/$path',
      data: <String, dynamic>{
        'message': message,
        'content': content,
        'access_token': await getAccessToken()
      },
    );

    if (response.statusCode == 201) {
      return response;
    } else {
      throw Exception('Failed to load branches: ${response.statusCode}');
    }
  }

  /// 上传文件
  Future<String> updateFile(
      {String owner = _owner,
      required String repo,
      required String sha,
      required String path,
      required String content,
      required String message}) async {
    final response = await _dio.put(
      '/api/v5/repos/$owner/$repo/contents/$path',
      data: <String, dynamic>{
        'message': message,
        'content': content,
        'sha': sha,
        'access_token': await getAccessToken()
      },
    );
    Logger().i(response.data);
    if (response.statusCode == 200) {
      // 解析commit.sha
      final data = response.data;
      final commitSha = data['content']?['sha'] ?? '';
      return commitSha;
    } else {
      throw Exception('Failed to load branches: ${response.statusCode}');
    }
  }
}
